/**
 * 交换值 返回val不相等的值
 * @param {T} val 值
 * @param {T} v1 值
 * @param {T} v2 值
 */
export const exchangeValue = <T>(val:T, v1:T, v2:T):T => {
  if(val === v1){
    return v2;
  }
  if(val === v2){
    return v1;
  }
  return val;
}

/**
 * 复制
 * @param {T} val 值
 */
export const clone = <T>(val:T):T => {
  return JSON.parse(JSON.stringify(val))
}


/**
 * 分配data1 值增加data2非空属性
 * @param {T} data1 值
 * @param {T} data2 值2
 */
 export const assign = (data1:any, data2:any):any => {
  Object.keys(data2).forEach(key => {
    const val = data2[key]
    if (val || val === 0) {
      data1[key] = val
    }
  })
  return data1
}


interface ITree{
  children:ITree[]
}


/**
 * 树结构递归循环
 * @param {*} tree 树结构数据
 * @param {*} leafCall 叶子节点操作
 * @param {*} notLeafCall 非叶子节点操作
 */
export const treeForEach = (tree:ITree[], leafCall?:Function, notLeafCall?:Function):void => {
  tree.forEach(e=>{
    if(e.children && e.children.length>0){
      if(notLeafCall){
        notLeafCall(e)
      }
      treeForEach(e.children, leafCall, notLeafCall)
      return
    }
    if(leafCall){
      leafCall(e)
    }
  })
}


/**
 * 时间转换成日期
 * @param {any} val 2020-01-01 00:00:00
 * @returns 2020-01-01
 */
 export const timeToDate = (time:string):string => {
  if (time) {
    var array = time.split(" ");
    if (array.length == 2) {
      return time.split(" ")[0];
    }
  }
  return "";
}


/**
 * param 将要转为URL参数字符串的对象
 * key URL参数字符串的前缀
 * encode true/false 是否进行URL编码,默认为true
 * 
 * return URL参数字符串
 */
 export const urlEncode = function (param:any, key?:string, encode?:boolean) {
  if(param==null) return '';
  var paramStr = '';
  var t = typeof (param);
  if (t == 'string' || t == 'number' || t == 'boolean') {
    paramStr += '&' + key + '=' + ((encode==null||encode) ? encodeURIComponent(param) : param);
  } else {
    for (var i in param) {
      var k = key == null ? i : key + (param instanceof Array ? '[' + i + ']' : '.' + i);
      paramStr += urlEncode(param[i], k, encode);
    }
  }
  return paramStr;
 }

/**
 *  清理对象
 * @param obj 相关对象
 * @param ignore 排除属性
 */
export const clearObject = (obj:any, ...ignore:string[]) => {
  Object.keys(obj).map(key=>{
    if(ignore.indexOf(key) < 0){
      const val = obj[key]
      if(undefined === val || null === val || '' === val || 0 === val || (val instanceof Array && val.length === 0)){
        delete obj[key]
      }
    }
  })
}

/**
 * 删除key包含
 */
export const deleteKeyInclude = (obj:any, ...delKeys:string[]) => {
  Object.keys(obj).map(key=>{
    if(delKeys.indexOf(key) >= 0){
      delete obj[key]
    }
  })
}

/**
 * 删除key跳过
 */
export const deleteKeyIgnore = (obj:any, ...ignore:string[]) => {
  Object.keys(obj).map(key=>{
    if(ignore.indexOf(key) === -1){
      delete obj[key]
    }
  })
}

const delayMap:Map<string,boolean> = new Map();
/**
 * 单次执行(方法在延迟时间内只执行一次)
 * @param call 执行方法
 * @param key  唯一key
 * @param delayTime 延迟时间(毫秒数)
 * @returns 
 */
export const singleExecute = (call:Function, key:string, delayTime:number) => {
  const val = delayMap.get(key)
  if(val){
    return
  }
  call()
  delayMap.set(key, true)
  setTimeout(()=>{
    delayMap.delete(key)
  }, delayTime)
}


/**
 * 存入 storage 转换为字符串
 * @param value 
 * @returns 
 */
const stringifyStorage = (value:string|object):string => {
  if((typeof value === 'object')){
    return JSON.stringify(value);
  }
  return value;
}
/**
 * 取出 storage 转换为对象，或直接字符串
 * @param value 
 * @returns 
 */
const parseStorage = (value:string|null):string|object|null => {
  if(!value){
    return null;
  }
  if(
    (value.startsWith('{') && value.endsWith('}')) ||
    (value.startsWith('[') && value.endsWith(']'))
  ){
    return JSON.parse(value)
  }
  return value;
}

export const getLocal = (key:string):string|object|null => {
  const value = localStorage.getItem(key)
  return parseStorage(value);
}
export const setLocal = (key:string, value:string|object|undefined):void => {
  if(value=== undefined || value === null){
    localStorage.removeItem(key)
    return
  }
  localStorage.setItem(key, stringifyStorage(value));
}

export const getSession = (key:string):string|object|null => {
  const value = sessionStorage.getItem(key)
  return parseStorage(value);
}

export const setSession = (key:string, value:string|object|undefined):void => {
  if(value=== undefined || value === null){
    sessionStorage.removeItem(key)
    return
  }
  sessionStorage.setItem(key, stringifyStorage(value));
}

const tokenKey = process.env.VUE_APP_TOKEN || 'token'

export const getTokenKey = () => {
	return tokenKey
}

// 清空登录缓存
export const clearLoginCache = () => {
  setSession('devcloud-openKeys', undefined)
  setSession('devcloud-selectedKeys', undefined)
	setSession('devcloud-auth', undefined)
	setLocal(tokenKey, undefined)
	setLocal('account', undefined)
}